package com.xwj.validation.basic.controller;

import com.alibaba.fastjson.JSON;
import com.xwj.common.util.R;
import com.xwj.common.util.enums.CommonErrorEnum;
import com.xwj.validation.basic.dto.StudentDTO;
import com.xwj.validation.common.utils.ErrorResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.URL;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.Min;

/**
 * @Author: xiaowajiang
 * @Date: 2022-03-13 15:34
 * @Description:
 *
 * 校验 @RequestBody 注解修饰的对象实体参数，具体操作如下：
 * 1. 在 Bean 对象的属性上添加校验约束注解
 * 2. 在参数对象实体前面加上 @Valid 注解，开启校验
 * 3. 在参数对象后面添加 BindingResult 对象，获取校验结果
 *
 * 校验 @RequestParam/@PathVariable 注解修饰的参数，操作如下：
 * 1. 在类上添加 @Validated 注解，开启校验
 * 2. 在接口入参上声明校验约束注解(如 @NotNull、@Min(10000))
 **/
@Slf4j
@RestController
@Validated
@Api(value = "BasicValidController", tags = "基础校验")
public class BasicValidController {

    @ApiOperation(value = "请求体中发送 JSON 数据", notes = "校验失败后，抛出 MethodArgumentNotValidException 异常", position=1)
    @PostMapping("basic/valid/student/saveStudentWithJson")
    public R saveStudentWithJson(@Validated @RequestBody StudentDTO stu) {
        log.info("保存学员信息，入参：{}", JSON.toJSONString(stu));
        // 业务逻辑
        return R.ok();
    }

    @ApiOperation(value = "请求体中发送 JSON 数据", notes = "使用 BindingResult 对象可以获取校验失败的结果", position=2)
    @PostMapping("basic/valid/student/updateStudentWithJson")
    public R updateStudentWithJson(@Validated @RequestBody StudentDTO stu, BindingResult result) {
        log.info("修改学员信息，入参：{}", JSON.toJSONString(stu));
        if (result.hasErrors()) {
            CommonErrorEnum errorEnum = CommonErrorEnum.PARAM_BIND_ERROR;
            return R.error(errorEnum.getCode(), errorEnum.getMessage()).put("data", ErrorResultUtil.getErrorMap(result));
        }
        // 业务逻辑
        return R.ok();
    }


    @ApiOperation(value = "请求体中发送 form-data 数据", notes = "校验失败后，抛出 BindException 异常", position=3)
    @PostMapping("basic/valid/student/saveStudentWithForm")
    public R saveStudentWithForm(@Valid StudentDTO stu) {
        log.info("保存学员信息，入参：{}", JSON.toJSONString(stu));
        // 业务逻辑
        return R.ok();
    }

    @ApiOperation(value = "URL Query传参", notes = "校验失败后，抛出 ConstraintViolationException 异常", position=4)
    @PostMapping("basic/valid/student/update/photo")
    public R updatePhoto(@RequestParam Long id, @URL @RequestParam String photo) {
        log.info("修改学员头像，入参：{}, {}", id, photo);
        // 业务逻辑
        return R.ok();
    }

    @ApiOperation(value = "Path Info传参", notes = "校验失败后，抛出 ConstraintViolationException 异常", position=5)
    @PostMapping("basic/valid/student/info/{id}")
    public R updatePhoto(@Min(10000) @PathVariable Long id) {
        log.info("查询学员信息，入参：{}", id);
        // 业务逻辑
        return R.ok();
    }

}
